package com.xbongbong.paas.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.crm.abstracts.AbstractCrmAddDataService;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.PaasFormSubDataEntity;
import com.xbongbong.paas.domain.entity.PaasStageEntity;
import com.xbongbong.paas.domain.entity.StageProcessEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.StageTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.PaasFormHelp;
import com.xbongbong.paas.help.ProFormHelp;
import com.xbongbong.paas.log.thread.LogThreadPoolBeanConfig;
import com.xbongbong.paas.model.PaasFormPaasSubDataModel;
import com.xbongbong.paas.model.PaasStageModel;
import com.xbongbong.paas.model.StageLogModel;
import com.xbongbong.paas.model.StageProcessModel;
import com.xbongbong.paas.pojo.FormTitlePoJo;
import com.xbongbong.paas.pojo.dto.FormDataAddDTO;
import com.xbongbong.paas.pojo.dto.SaasFormSaveDTO;
import com.xbongbong.paas.pojo.vo.FormDataAddVO;
import com.xbongbong.paas.service.DetailStageService;
import com.xbongbong.paas.service.PaasFormDataService;
import com.xbongbong.paas.service.dynamic.crm.strategy.DynamicStrategyFactory;
import com.xbongbong.paas.service.dynamic.help.DynamicHelp;
import com.xbongbong.paas.service.team.TeamDataHelp;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.paas.util.FormDataUtil;
import com.xbongbong.paas.util.ItemUtil;
import com.xbongbong.paas.util.TitleUtil;
import com.xbongbong.parent.factory.StageExecuteFactory;
import com.xbongbong.parent.interfaces.StageExecuteHandle;
import com.xbongbong.parent.parse.data.FormDataListAnalysisDataHelp;
import com.xbongbong.pro.businesstage.pojo.dto.CommonJumpDTO;
import com.xbongbong.pro.domain.entity.ReRollBackEntity;
import com.xbongbong.pro.enums.PaasStageEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.BuinessDefaultErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.formdata.pojo.vo.BeforeSaveVO;
import com.xbongbong.pro.formdata.pojo.vo.SaveVO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.model.PaasFormDataModel;
import com.xbongbong.paas.data.service.RichTextService;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import org.elasticsearch.action.support.WriteRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author 吴峰
 * @date 2021/02/03 11:07
 */
@Service("paasDataFormDataServiceImpl")
public class PaasDataFormDataServiceImpl extends AbstractCrmAddDataService {

    private static final Logger LOG = LoggerFactory.getLogger(PaasDataFormDataServiceImpl.class);
    @Resource
    private PaasFormDataModel paasFormDataModel;
    @Resource
    private LogThreadPoolBeanConfig logThreadPoolBeanConfig;
    @Resource
    private ProFormHelp proFormHelp;
    @Resource
    private PaasStageModel paasStageModel;
    @Resource
    private StageProcessModel stageProcessModel;
    @Resource
    private StageExecuteFactory stageExecuteFactory;
    @Resource
    private PaasFormDataService paasFormDataService;
    @Resource
    private TeamDataHelp teamDataHelp;
    @Resource
    private DynamicHelp dynamicHelp;
    @Resource
    private PaasFormPaasSubDataModel paasFormPaasSubDataModel;

    @Override
    public List<Integer> businessList() {
        return Arrays.asList(XbbRefTypeEnum.PAAS.getCode());
    }

    @Override
    public void afterSaveLog(FormDataAddDTO formDataAddDTO, PaasFormEntityExt paasFormEntityExt, PaasFormDataEntity newPaasFormDataEntity, SaveVO saveVO, BeforeSaveVO beforeSaveVO) throws XbbException {
        boolean isImport = Objects.equals(1, formDataAddDTO.getIsImport());
        if (isImport) {
            return;
        }
        Runnable runnable = () -> {
            try {
                Map<String, FieldAttrEntity> explainMap = beforeSaveVO.getExplainMap();
                List<FieldAttrEntity> list = new ArrayList<>();
                Iterator<String> iterator = explainMap.keySet().iterator();
                while (iterator.hasNext()) {
                    String attr = iterator.next();
                    FieldAttrEntity fieldAttrEntity = explainMap.get(attr);
                    list.add(fieldAttrEntity);
                }
                PaasFormDataEntityExt paasFormDataEntityExt = new PaasFormDataEntityExt();
                BeanUtil.copyProperties(newPaasFormDataEntity, paasFormDataEntityExt);
                List<FormTitlePoJo> formTitleList = ExplainUtil.getFormTitle(JSONArray.parseArray(paasFormEntityExt.getCustomTitle()), explainMap, paasFormDataEntityExt.getData(), list, paasFormDataEntityExt);
                String title = "";
                if(!formTitleList.isEmpty()){
                    formTitleList.forEach(titlePoJo->{
                        FieldAttrEntity fieldAttrEntity = explainMap.get(titlePoJo.getAttr());
                        if (Objects.nonNull(fieldAttrEntity) && ExplainUtil.isCombo(fieldAttrEntity.getFieldType())) {
                            JSONObject jsonObject = new JSONObject();
                            jsonObject.put(titlePoJo.getAttr(), titlePoJo.getValue());
                            Object value = ItemUtil.analysisComboReturnStr(jsonObject, fieldAttrEntity);
                            titlePoJo.setValue(Collections.singletonList(value));
                        }
                    });
                    title = TitleUtil.getTitle(formTitleList);
                }
                if(StringUtil.isEmpty(title)){
                    title = "--";
                }
                saveLogger(formDataAddDTO, newPaasFormDataEntity, title, paasFormEntityExt.getName(), OperateModuleTypeEnum.PAAS_FORM_DATA, saveVO, beforeSaveVO);
            } catch (Exception e) {
                LOG.error("com.xbongbong.paas.service.impl.paasDataFormDataServiceImpl.afterSaveLog fail", e);
            }
        };
        logThreadPoolBeanConfig.sysLogThreadPool().execute(runnable);
    }

    @Override
    public SaveVO save(FormDataAddDTO formDataSaveDTO, BeforeSaveVO beforeSaveVO, PaasFormEntityExt paasFormEntity, PaasFormDataEntity paasFormDataEntity) throws XbbException {
        Integer saasMark = formDataSaveDTO.getSaasMark();
        Integer businessType = formDataSaveDTO.getBusinessType();
        String corpid = formDataSaveDTO.getCorpid();
        Long dataId = 0L;
        try {
            UserVO userVO = new UserVO();
            Integer noApprovalRequired = beforeSaveVO.getNoApprovalRequired() ;
            if (Objects.equals(1, noApprovalRequired)) {
                if (Objects.nonNull(formDataSaveDTO.getProcessCreatorId()) && Objects.isNull(paasFormDataEntity.getOwnerId())) {
                    paasFormDataEntity.setOwnerId(formDataSaveDTO.getProcessCreatorId());
                }
                //移除富文本
                JSONObject data = paasFormDataEntity.getData();
                Object richTextData = removeRichText(data);
                FormDataUtil.removeSystemData(data);
                if (Objects.equals(1, formDataSaveDTO.getIsBusinessRule())) {
                    paasFormDataModel.insert(paasFormDataEntity, WriteRequest.RefreshPolicy.WAIT_UNTIL);
                } else {
                    paasFormDataModel.insert(paasFormDataEntity);
                }

                dataId = paasFormDataEntity.getId();
                userVO = getUserName(formDataSaveDTO, paasFormDataEntity);
                //文件柜数据保存
                saveFile(formDataSaveDTO, paasFormDataEntity, userVO);
                //富文本数据保存
                saveRichText(formDataSaveDTO, paasFormDataEntity, richTextData);

                beforeSaveVO.setPaasFormDataEntity(paasFormDataEntity);
            }
            return new SaveVO(noApprovalRequired, paasFormDataEntity, dataId, userVO);
        } catch (XbbException e) {
            LOG.warn(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            saveRollBack(dataId, corpid, saasMark, businessType);
            throw e;
        } catch (Exception e) {
            LOG.error(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            saveRollBack(dataId, corpid, saasMark, businessType);
            throw e;
        }
    }

    @Override
    public void saveRollBack(Long id, String corpid, Integer saasMark, Integer businessType) throws XbbException {
        if (id == null || id == 0 || corpid == null || saasMark == null) {
            return ;
        }
        IndexTypeEnum indexTypeEnum = getIndexTypeEnum(corpid, saasMark, businessType);
        //删除主表es数据
        physicalDeleteFormData(id, corpid, indexTypeEnum);
        // 子表单的删除
        List<PaasFormSubDataEntity> paasFormSubDataEntities = paasFormPaasSubDataModel.getByDataId(id, corpid);
        if (CollectionsUtil.isNotEmpty(paasFormSubDataEntities)) {
            physicalDeleteSubBatch(corpid, paasFormSubDataEntities, IndexTypeEnum.IDX_SUB_FORM_DATA);
        }
    }

    @Override
    public FormDataAddVO afterSave(FormDataAddDTO formDataAddDTO, BeforeSaveVO beforeSaveVO, SaveVO saveVO, PaasFormEntityExt paasFormEntity, PaasFormDataEntity paasFormDataEntity) throws XbbException {
        FormDataAddVO formDataAddVO = new FormDataAddVO();
        Long dataId = saveVO.getDataId();
        String corpid = formDataAddDTO.getCorpid();
        Integer saasMark = formDataAddDTO.getSaasMark();
        Integer businessType = formDataAddDTO.getBusinessType();
        ReRollBackEntity reRollBackEntity = new ReRollBackEntity();

        try {
            Integer noApprovalRequired = saveVO.getNoApprovalRequired();
            if (Objects.equals(1, noApprovalRequired)) {
                SaasFormSaveDTO saasFormSaveDTO = new SaasFormSaveDTO();
                BeanUtil.copyProperties(formDataAddDTO, saasFormSaveDTO);
                packageSaasFormInsertSaveDTO(saasFormSaveDTO, paasFormDataEntity);

                // 团队保存
                teamDataHelp.saveUserTeam(saasFormSaveDTO.getSaasNeedRedundantAttrPoJo(), saasFormSaveDTO.getNewPaasFormDataEntity().getId(), saasFormSaveDTO.getNewPaasFormDataEntity(), saasFormSaveDTO.getIsImport(), false);

                // 记录日志
                afterSaveLog(formDataAddDTO, paasFormEntity, paasFormDataEntity, saveVO, beforeSaveVO);
                // api
                apiHook(formDataAddDTO, saveVO, beforeSaveVO);
                // 业务规则
                activeRule(formDataAddDTO, beforeSaveVO, paasFormDataEntity, beforeSaveVO.getPaasFormEntityExt());

                //阶段处理
                afterSaveStage(saasFormSaveDTO);
                // 动态处理
                dynamicHelp.addLinkData(saasFormSaveDTO);

                formDataAddVO.setMsg(I18nMessageUtil.getMessage(MessageConstant.FORM_ADD_RETURN_MSG));
                formDataAddVO.setCode(PaasConstant.FORM_ADD_RETURN_CODE);
                formDataAddVO.setDataId(paasFormDataEntity.getId());
            }else {
                formDataAddVO.setMsg(I18nMessageUtil.getMessage(MessageConstant.FORM_ADD_PROCESS_RETURN_MSG));
                formDataAddVO.setCode(PaasConstant.FORM_ADD_PROCESS_RETURN_CODE);
            }
            formDataAddVO.setFormDataId(paasFormDataEntity.getId());
        } catch (XbbException e) {
            LOG.warn(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            afterSaveRollBack(paasFormDataEntity, dataId, corpid, saasMark, businessType, reRollBackEntity);
            throw e;
        } catch (Exception e) {
            LOG.error(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            afterSaveRollBack(paasFormDataEntity, dataId, corpid, saasMark, businessType, reRollBackEntity);
            throw new XbbException(BuinessDefaultErrorCodeEnum.API_ERROR_200018);
        }
        return formDataAddVO;
    }


    /**
     * @Author sunshaoxiang
     * @Description 新建阶段数据 相关的afterSave 操作
     * @param saasFormSaveDTO
     * @return
     **/
    public void afterSaveStage(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        boolean isNew = saasFormSaveDTO.getIsNew();
        boolean hasStageField = false;
        boolean isFromProcess = Objects.equals(saasFormSaveDTO.getIsFromProcess(), BasicConstant.ONE);
        String corpid = saasFormSaveDTO.getCorpid();
        JSONObject newData = saasFormSaveDTO.getNewData();
        JSONObject oldData = saasFormSaveDTO.getOldData();
        Integer businessType = saasFormSaveDTO.getBusinessType();
        PaasFormDataEntity newPaasFormDataEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
        Long dataId = newPaasFormDataEntity.getId();
        Long formId = newPaasFormDataEntity.getFormId();
        PaasFormExplainEntity explainEntity = proFormHelp.getExplainEntity(corpid, formId, businessType);
        List<FieldAttrEntity> fieldAttrEntities = JSON.parseArray(explainEntity.getExplains(), FieldAttrEntity.class);

        String stageAttr = "";
        for (FieldAttrEntity fieldAttrEntity : fieldAttrEntities) {
            if (Objects.equals(FieldTypeEnum.STAGE_THRUSTER.getType(), fieldAttrEntity.getFieldType()) && Objects.equals(BasicConstant.ONE, fieldAttrEntity.getIsOpen())){
                hasStageField = true;
                stageAttr = fieldAttrEntity.getAttr();
                break;
            }
        }
        //判断有没有阶段推进器字段
        if (hasStageField) {
            Long stageProcessId = FastJsonHelper.getLongOrDefaultFromFormData(newData, PaasStageEnum.STAGE_PROCESS_ID.getAttr(), BasicConstant.ZERO_LONG);
            StageProcessEntity stageProcessEntity = stageProcessModel.getByKey(stageProcessId, corpid);
            Long toStageId = FastJsonHelper.getLongOrDefaultFromFormData(newData, PaasStageEnum.STAGE_ID.getAttr(), BasicConstant.ZERO_LONG);
            Long fromStageId = FastJsonHelper.getLongOrDefaultFromFormData(oldData, PaasStageEnum.STAGE_ID.getAttr(), BasicConstant.ZERO_LONG);
            PaasStageEntity toStageEntity = paasStageModel.getByKey(toStageId, corpid);
            PaasStageEntity fromStageEntity = paasStageModel.getByKey(fromStageId, corpid);
            //判断阶段是否发生阶段改变,发生阶段改变才需要跳转
            boolean isChangeStage = !Objects.equals(toStageId, BasicConstant.ZERO_LONG);
            if (isChangeStage) {
                //封装阶段跳转参数
                try {
                    StageExecuteHandle stageExecute = stageExecuteFactory.getStageExecute(SaasMarkEnum.PAAS.getCode(), businessType);
                    CommonJumpDTO commonJumpDTO = new CommonJumpDTO();
                    // 从BaseDTO拷贝loginUser等基础信息
//                    BeanUtil.copyProperties(saasFormSaveDTO, commonJumpDTO);
                    commonJumpDTO.setIsImport(saasFormSaveDTO.getIsImport());
                    commonJumpDTO.setPlatform(saasFormSaveDTO.getPlatform());
                    commonJumpDTO.setSaasMark(SaasMarkEnum.PAAS.getCode());
                    commonJumpDTO.setBusinessType(businessType);
                    commonJumpDTO.setFormId(formId);
                    commonJumpDTO.setDataId(dataId);
                    commonJumpDTO.setCorpid(corpid);
                    commonJumpDTO.setUserId(isFromProcess ? saasFormSaveDTO.getProcessCreatorId() : saasFormSaveDTO.getUserId());
                    //新建数据相当于从开始阶段跳转（详情页跳转需要这样特殊处理）
                    commonJumpDTO.setFromStageType(StageTypeEnum.START_STAGE.getType());
                    commonJumpDTO.setToStageType(toStageEntity.getType());
                    commonJumpDTO.setFromStageEntity(fromStageEntity);
                    commonJumpDTO.setToStageEntity(toStageEntity);
                    commonJumpDTO.setStageProcessEntity(stageProcessEntity);
                    commonJumpDTO.setStageAttr(stageAttr);
                    commonJumpDTO.setFromApproval(BasicConstant.ONE);
                    commonJumpDTO.setIsNew(isNew);
                    commonJumpDTO.setFromOuterLink(saasFormSaveDTO.getFromOuterLink());
                    stageExecute.stageCommonJump(commonJumpDTO);
                } catch (XbbException e) {
                    LOG.error("PaasDataFormDataServiceImpl.stageCommonJump出错:", e);
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
                }
            }
        }
    }

    @Override
    public void apiHook(FormDataAddDTO formDataAddDTO, SaveVO saveVO, BeforeSaveVO beforeSaveVO) throws XbbException {
        LOG.info("paas form data api hook");
        lowCodeExecuteService(formDataAddDTO, saveVO, beforeSaveVO);
    }

    @Override
    public SaveVO saveForWorkflow(FormDataAddDTO formDataAddDTO, BeforeSaveVO beforeSaveVO, PaasFormEntityExt paasFormEntity, PaasFormDataEntity paasFormDataEntity) throws XbbException {
        Integer saasMark = formDataAddDTO.getSaasMark();
        Integer businessType = formDataAddDTO.getBusinessType();
        String corpid = formDataAddDTO.getCorpid();
        Long dataId = 0L;
        try {
            UserVO userVO = new UserVO();
            Integer noApprovalRequired = beforeSaveVO.getNoApprovalRequired() ;
            if (Objects.nonNull(formDataAddDTO.getProcessCreatorId()) && Objects.isNull(paasFormDataEntity.getOwnerId())) {
                paasFormDataEntity.setOwnerId(formDataAddDTO.getProcessCreatorId());
            }
            FormDataUtil.removeSystemData(paasFormDataEntity.getData());
            Object richTextData = removeRichText(paasFormDataEntity.getData());
            paasFormDataModel.insert(paasFormDataEntity);

            dataId = paasFormDataEntity.getId();
            userVO = getUserName(formDataAddDTO, paasFormDataEntity);
            //文件柜数据保存
//                saveFile(formDataAddDTO, paasFormDataEntity, userVO);

            //富文本数据保存
            saveRichText(formDataAddDTO, paasFormDataEntity, richTextData);
            beforeSaveVO.setPaasFormDataEntity(paasFormDataEntity);

            return new SaveVO(noApprovalRequired, paasFormDataEntity, dataId, userVO);
        } catch (XbbException e) {
            LOG.warn(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            saveRollBack(dataId, corpid, saasMark, businessType);
            throw e;
        } catch (Exception e) {
            LOG.error(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            saveRollBack(dataId, corpid, saasMark, businessType);
            throw e;
        }
    }

    @Override
    public FormDataAddVO afterSaveForWorkflow(FormDataAddDTO formDataAddDTO, BeforeSaveVO beforeSaveVO, SaveVO saveVO, PaasFormEntityExt paasFormEntity, PaasFormDataEntity paasFormDataEntity) throws XbbException {
        FormDataAddVO formDataAddVO = new FormDataAddVO();
        Long dataId = saveVO.getDataId();
        String corpid = formDataAddDTO.getCorpid();
        Integer saasMark = formDataAddDTO.getSaasMark();
        Integer businessType = formDataAddDTO.getBusinessType();
        ReRollBackEntity reRollBackEntity = new ReRollBackEntity();

        try {
//            Integer noApprovalRequired = saveVO.getNoApprovalRequired();
            SaasFormSaveDTO saasFormSaveDTO = new SaasFormSaveDTO();
            BeanUtil.copyProperties(formDataAddDTO, saasFormSaveDTO);
            packageSaasFormInsertSaveDTO(saasFormSaveDTO, paasFormDataEntity);
            paasFormDataService.afterSaveForWorkflow(saasFormSaveDTO);
            // 记录日志
//            afterSaveLog(formDataAddDTO, paasFormDataEntity, saveVO, beforeSaveVO);
            // api
//            apiHook(formDataAddDTO, saveVO, beforeSaveVO);
            // 业务规则
//            activeRule(formDataAddDTO, beforeSaveVO, paasFormDataEntity, beforeSaveVO.getPaasFormEntityExt());

            formDataAddVO.setDataId(paasFormDataEntity.getId());
            formDataAddVO.setFormDataId(paasFormDataEntity.getId());
            formDataAddVO.setMsg(I18nMessageUtil.getMessage(MessageConstant.FORM_ADD_RETURN_MSG));
            formDataAddVO.setCode(PaasConstant.FORM_ADD_RETURN_CODE);
//        } catch (XbbException e) {
//            LOG.warn(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
//            afterSaveRollBack(paasFormDataEntity, dataId, corpid, saasMark, businessType, reRollBackEntity);
//            throw e;
        } catch (Exception e) {
            LOG.error(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            afterSaveRollBack(paasFormDataEntity, dataId, corpid, saasMark, businessType, reRollBackEntity);
            throw new XbbException(BuinessDefaultErrorCodeEnum.API_ERROR_200018);
        }
        return formDataAddVO;
    }


    @Override
    public void afterSaveRollBack(PaasFormDataEntity newPaasFormDataEntity, Long dataId, String corpid, Integer saasMark, Integer businessType, ReRollBackEntity reRollBackEntity) throws XbbException {
        try {
            saveRollBack(dataId, corpid, saasMark, businessType);

        } catch (Exception e) {
            LOG.error("abstractFormDataServiceImpl.afterSaveRollBack 回滚失败：", e);
        }

    }
}
